<template>
  <div style="width: 100%;height: 100%;position: relative;" @mouseout="resetMouse">

    <div style="width: 100%;height: 100%;"
      :style="{ 'backdrop-filter': 'blur(' + blur + ')', ' -webkit-backdrop-filter': 'blur(' + blur + ')' }">
      <!-- <div style="position: absolute;top: 0;left: 0;right: 0;bottom: 0;">
        <lightning :hue="230" :xOffset="0" :speed="1" :intensity="0.1" :size="1" />
      </div> -->
      <div ref="cameraCanvas" :style="{ 'backgroundImage': backgroundImage }"
        style="width: 100%;height: 100%;position: fixed;top: 0;left: 0;right: 0;bottom: 0;">
      </div>
    </div>
    <div
      style="position: absolute;top: 0;left: 0;right: 0;bottom: 0;background-color: rgba(0, 0, 0, 0.01);backdrop-filter: blur(1px);-webkit-backdrop-filter:blur(1px)'">
    </div>
  </div>
</template>
<script>
export default {
  name: "a-rain",
}
</script>
<script setup>
// import lightning from "@/components/a-lightning.vue";
import { onMounted, ref, defineProps, reactive, onBeforeUnmount } from 'vue';
import * as THREE from 'three';
import { Lensflare, LensflareElement } from 'three/addons/objects/Lensflare.js';

const props = defineProps({
  level: {
    type: Number,
    default: 0
  }
});

const backgroundImage = ref('linear-gradient(rgba(0,0,0,0.9), rgba(13,13,59,0))')
const blur = ref('0px')

// 使用ref创建一个引用，用于获取canvas元素
const cameraCanvas = ref(null);
// 定义全局变量，用于存储场景、相机、渲染器和粒子系统等对象
let scene, camera, renderer, cloudParticles = [], flash, rain, rainGeo, rainCount, rainMaterial;

/**
 * 初始化场景、相机、光源和粒子系统等
 */
function initialize() {
  if (props.level === 1) {
    backgroundImage.value = 'linear-gradient(rgba(0,0,0,0.4), transparent)'
    blur.value = '0px'
  } else if (props.level === 2) {
    backgroundImage.value = 'linear-gradient(rgba(0,0,0,0.7), transparent)'
    blur.value = '1px'
  } else if (props.level === 3) {
    backgroundImage.value = 'linear-gradient(rgba(0,0,0,0.9), rgba(13,13,59,0.1))'
    blur.value = '2px'
  }
  rainCount = 500 + 10000 * ((props.level - 1) / 2)
  scene = new THREE.Scene();
  camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
  camera.position.x = 0;
  camera.position.y = 0;
  camera.position.z = 100;

  addLights();
  initializeRenderer();
  initializeRain();
  initializeClouds();
}

/**
 * 添加环境光和方向光
 */
function addLights() {
  let ambient = new THREE.AmbientLight(0x555555);
  scene.add(ambient);

  let directionalLight = new THREE.DirectionalLight(0xffeedd);
  directionalLight.position.set(0, 0, 1);
  scene.add(directionalLight);
  // 初始化闪光灯
  flash = new THREE.PointLight(0xffffff, 30, 500, 0);
  flash.color.setHSL(0.1, 0.8, 0.8);

  flash.position.set(0,
    400,
    -400);
  scene.add(flash);
}

/**
 * 初始化渲染器
 */
function initializeRenderer() {
  renderer = new THREE.WebGLRenderer();
  scene.fog = new THREE.FogExp2(0x11111f, 0.002);
  renderer.setClearColor(scene.fog.color);
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.setClearAlpha(0.4);

  if (cameraCanvas.value) {
    cameraCanvas.value.appendChild(renderer.domElement);
  }
}

/**
 * 初始化雨滴粒子系统
 */
function initializeRain() {
  // 雨滴形状的精灵纹理
  let texture = new THREE.TextureLoader().load('/assets/img/rainy.png'); // 加载雨滴形状的纹理

  const rainPositions = generateRandomPositions(rainCount);
  rainGeo = new THREE.BufferGeometry();
  rainGeo.setAttribute('position', new THREE.BufferAttribute(rainPositions, 3));

  rainMaterial = new THREE.PointsMaterial({
    map: texture,
    color: 0xffffff,
    opacity: 0.4,
    size: 14 + (props.level - 1) / 2 * 4,
    blending: THREE.AdditiveBlending,
    depthTest: false, // 解决透明度问题
    transparent: true
  });

  rain = new THREE.Points(rainGeo, rainMaterial);
  rain.rotation.z = 0;
  scene.add(rain);
}

/**
 * 生成随机位置数组用于粒子系统
 * @param {number} count - 粒子数量
 * @returns {Float32Array} 随机位置数组
 */
function generateRandomPositions(count) {
  const positions = new Float32Array(count * 3);
  for (let i = 0; i < count; i++) {
    positions[i * 3] = 50 + (Math.random() - 0.5) * 500;
    positions[i * 3 + 1] = (Math.random() - 0.5) * 500;
    positions[i * 3 + 2] = -Math.random() * 200;
  }
  return positions;
}

/**
 * 初始化云朵
 */
function initializeClouds() {
  let loader = new THREE.TextureLoader();
  loader.load("/assets/img/cloud3.png", function (texture) {
    const lensflare = new Lensflare();
    lensflare.addElement(new LensflareElement(texture, 700, 500, flash.color));
    flash.add(lensflare);
    createClouds(texture);
    animate();
  });
}

/**
 * 创建云朵
 * @param {THREE.Texture} texture - 云朵纹理
 */
function createClouds(texture) {
  let cloudGeo = new THREE.PlaneGeometry(100, 100);
  let c = 15 + (props.level - 1) / 2 * 30
  // 0.4 亮度，乌云的话可以用0.1
  for (let p = 0; p < c; p++) {
    let cloudMaterial = new THREE.MeshLambertMaterial({
      map: texture,
      transparent: true
    });
    cloudMaterial.color.setHSL(1, 0, 0.2 + Math.random() * 0.1);
    let cloud = new THREE.Mesh(cloudGeo, cloudMaterial);
    cloud.position.set((Math.random() - 0.5) * 400, 80 + Math.random() * 6, -Math.random() * 30);
    cloud.rotation.z = Math.random() * 360;
    cloud.material.opacity = 0.5 + Math.random() * 0.2;
    cloudParticles.push(cloud);
    scene.add(cloud);
  }
}

/**
 * 动画函数，用于更新粒子系统和进行渲染
 */
function animate() {
  updateClouds();
  updateRain();
  updateFlash();
  renderer.render(scene, camera);
  requestAnimationFrame(animate);
}

/**
 * 更新云朵粒子的位置
 */
function updateClouds() {

  cloudParticles.forEach(p => {
    p.rotation.z -= 0.002 * Math.random();
    p.position.x -= 0.01 + 0.01 * Math.random();
    if (p.position.x < -200) {
      p.position.set(150 + Math.random() * 100, 80 + Math.random() * 10, -Math.random() * 30);
    }
  });
}

/**
 * 更新雨滴粒子的位置
 */
function updateRain() {
  const positionAttribute = rainGeo.attributes.position;
  const vertices = new Float32Array(positionAttribute.array);
  // 鼠标影响幅度（减小系数）
  const mouseInfluenceX = mouseOffset.x * 0.2; // 原来是2
  const mouseInfluenceY = (mouseOffset.x + mouseOffset.y) * 0.4; // 原来是1.5
  for (let i = 0; i < vertices.length; i += 3) {
    vertices[i + 2] += 0.1 + Math.random() * 0.1;
    vertices[i + 1] -= 2 + Math.random() * 0.1 + (props.level - 1) / 2 * 1;
    vertices[i] -= 0.5 + Math.random() * 0.02 + (props.level - 1) / 2 * 0.2;
    // 鼠标影响
    vertices[i] += mouseInfluenceX;
    vertices[i + 1] += mouseInfluenceY;
    if (vertices[i + 1] < -200) {
      vertices[i] = (Math.random() - 0.5) * 400;
      vertices[i + 1] = 50 + Math.random() * 500;
      vertices[i + 2] = -Math.random() * 200;
    }
  }
  positionAttribute.set(vertices);
  positionAttribute.needsUpdate = true;
}

/**
 * 更新闪光灯的位置和强度
 */
function updateFlash() {
  if (Math.random() < 0.01 || flash.power > 0) {
    let r = Math.random();
    if (flash.power <= 0) {
      flash.position.set((Math.random() - 0.5) * 300, 80 + Math.random() * 10, 10 - Math.random() * 30);
      flash.power = 10 + ((props.level - 1) / 2) * (200 + r * 300);
    } else {
      let x = flash.power - (r - 0.2) * (5 + (props.level - 1) / 2 * 25);
      if (x < 0) {
        flash.power = 0
      } else {
        flash.position.x = flash.position.x + (Math.random() - 0.5) * (flash.power) / 20;
        flash.power = x;
      }
    }
  }
}


// 鼠标偏移量，范围[-1, 1]
const mouseOffset = reactive({ x: 0, y: 0 });
const resetMouse = () => {
  mouseOffset.x = 0;
  mouseOffset.y = 0;
};
function handleMouseMove(e) {
  // 鼠标超出窗口范围时，重置偏移并恢复雨滴
  if (
    e.clientX <= 0 || e.clientX >= window.innerWidth - 100 ||
    e.clientY <= 0 || e.clientY >= window.innerHeight
  ) {
    resetMouse();
  } else {
    mouseOffset.x = (e.clientX / window.innerWidth - 0.5) * 2; // -1 ~ 1
    mouseOffset.y = (e.clientY / window.innerHeight - 0.5) * 2; // -1 ~ 1
  }
}

// 在组件挂载时调用初始化函数，并添加窗口大小改变事件监听器
onMounted(() => {
  initialize();
  window.addEventListener('mousemove', handleMouseMove);
  window.addEventListener('blur', resetMouse);
  window.addEventListener('mouseleave', resetMouse);
});

onBeforeUnmount(() => {
  window.removeEventListener('mousemove', handleMouseMove);
  window.removeEventListener('blur', resetMouse);
  window.removeEventListener('mouseleave', resetMouse);
});

</script>


<style lang="less">
#img {
  display: none;
}

#canvas {
  position: absolute;
  top: 0px;
  left: 0px;
}

body {
  overflow: hidden;
  margin-top: 0;
  margin-bottom: 0;
  margin-left: 0;
  margin-right: 0;
}
</style>
